La Regenta
Análisis de la novela en R

Introducción

El R permite diferentes tipos de análisis de textos.

Dos tipos de texto. De un lado, una novela. De otro, una obra de teatro. Abren la posibilidad de comparar los resultados de los análisis de textos literarios.

Análisis de la novela “La Regenta”

Abrimos los datos

Code
# carga los datos de "La Regenta"
load("../textos/Regenta.RData")

Hacemos un análisis sumario de los capítulos

Code
# carga el paquete quanteda para 
# algunos análisis
library(quanteda)

# convierte en un documento corpus
cp <- corpus(regc, text_field = "texto")

# define los capítulos como nombre
# de los documentos
docnames(cp) <- regc$capitulo

# muestra estadísticas básicas de
# cada capítulo
summary(cp)
Corpus consisting of 32 documents, showing 32 documents:

          Text Types Tokens Sentences   parte      capitulo
  001 - Título    16     16         1  Título  001 - Título
 002 - Prólogo  1661   4649       101 Prólogo 002 - Prólogo
            01  3753  14662       466  Tomo I            01
            02  2236   8029       298  Tomo I            02
            03  2194   8395       384  Tomo I            03
            04  2448   9121       360  Tomo I            04
            05  3104  13640       542  Tomo I            05
            06  2312   8171       347  Tomo I            06
            07  2194   9012       391  Tomo I            07
            08  3178  13095       581  Tomo I            08
            09  2832  10992       492  Tomo I            09
            10  2096   8184       390  Tomo I            10
            11  3026  13356       529  Tomo I            11
            12  4169  18985       717  Tomo I            12
            13  3611  17074       541  Tomo I            13
            14  1980   8172       345  Tomo I            14
            15  2869  13484       531  Tomo I            15
            16  4022  17978       543 Tomo II            16
            17  2190   9804       332 Tomo II            17
            18  2793  10446       311 Tomo II            18
            19  2947  12333       407 Tomo II            19
            20  3753  16462       626 Tomo II            20
            21  3681  16554       676 Tomo II            21
            22  3256  14615       522 Tomo II            22
            23  2087   8302       308 Tomo II            23
            24  2031   8248       317 Tomo II            24
            25  2343  10096       476 Tomo II            25
            26  2812  12811       534 Tomo II            26
            27  3122  14099       642 Tomo II            27
            28  2889  13290       491 Tomo II            28
            29  3532  18228       716 Tomo II            29
            30  3724  21083       843 Tomo II            30

Hacemos un análisis de frecuencia de palabras

Code
# convierte en una matriz de términos
dtm <- dfm(tokens(cp, remove_punct = TRUE, 
                  remove_numbers = TRUE, 
                  remove_symbols = TRUE), 
           tolower = TRUE)

dtm <- dfm_remove(dtm, c(stopwords("es"),"si"))

# muestra las 50 palabras más frecuentes
topfeatures(dtm, 50)
      don       ana     usted magistral   aquella     aquel    álvaro    víctor 
     1791       897       822       769       761       733       490       489 
     casa   regenta     señor   vetusta      allí       ser   después      doña 
      482       468       458       455       450       437       417       414 
    decía       vez     mesía     podía     ahora      bien    fermín       así 
      414       392       373       369       364       353       350       347 
     ojos       dos       iba   siempre    quería       tan     menos      dijo 
      347       334       333       332       328       327       327       326 
     vida     mismo    hombre      dios     veces quintanar     mundo     mujer 
      324       320       315       310       307       305       290       286 
   tiempo     todas      alma       ver     sabía       día   parecía      amor 
      283       282       281       280       279       271       267       267 
  aquello     decir 
      265       259 

diccionario

Code
dic <- dictionary(
  list(
    familia=c("padre", "madre", "hijo", "hija", "hermano", "hermana"),
    sociedad=c("vetustense","puebl","ciudad","conversa","amig"),
    iglesia=c("cura","obispo","sacerdo","confesión","religi","canónig","capilla"),
    economia=c("dinero","deuda","negoci","trabaj","fortuna","rico","rica"),
    sentimientos=c("culpa","alegr","amor","remordimiento","ridículo","vergüenza","triste"),
    misticismo=c("Fermín de Pas","Fermín","\\bde Pas\\b", "magistral", "espirit","dios"),
    adulterio=c("Álvaro Mesía","Álvaro","Mesía","Presidente del Casino", "marido", "placer", "pasión", "amante","amorío"),
    espacio=c("casino","catedral","vivero","casa","espolón","teatro"),
    tiempo=c("otoño","verano","invierno","primavera","semana santa","navidad")
  )
)
    
library(tenet)
    
tagCorpus(cp, dic, reshape.to = "sentence")
Code
dicf <- dictionary(
  list(
    familia=c("padre", "madre", "hijo", "hija", "hermano", "hermana"),
    sociedad=c("vetustense","puebl","ciudad","conversa",
               "amig","noble","arist")
))


plotLexDiv(cp, dicf, title ="La Regenta", subtitle = "Familia y sociedad en la novela", palette = pal$cat.awtools.spalette.6[1:2])

Repetimos el mismo gráfico, ahora con las categorías de tiempo y espacio:

Code
dicf <- dictionary(
  list(
    espacio=c("casino","catedral","vivero","casa","espolón","teatro"),
    tiempo=c("otoño","verano","invierno","primavera","semana santa","navidad")
))

plotLexDiv(cp, dicf, title ="La Regenta", subtitle = "Espacio y tiempo en la novela", palette = pal$cat.brewer.Dark2.8[c(1:4)])

Code
dicf <- dictionary(
  list(
    social=c("casino","teatro"),
    religioso=c("catedral","capilla","sacristía",
                "claustro","seminario"),
    hogar=c("vivero","casa","hogar","alcoba","habitación"),
    paseos=c("espolón","Paseo de Verano","Paseo de los curas")
))



plotLexDiv(cp, dicf, title ="La Regenta", subtitle = "Tipos de espacio.", palette = pal$cat.brewer.Dark2.8[c(1:4)], hline.width = 2)

Code
xy <- countKeywords(cp, 
                    dic, 
                    rel.freq = F, 
                    quietly = TRUE)

# Elimina los términos no encontrados
xy <- xy[xy$frequency>0,]

xy$groups <- NULL

forceDirectedTree(xy,value_col = "frequency",
                  palette = pal$cat.awtools.bpalette.16, 
                  max.radius = 50, 
                  height = 500)

lo mismo se puede ver así:

Code
plotVoronoiTree(data = xy,
                value_col = "frequency")

dd

Juan Benito Argüelles - Nomina de personajes de “La Regenta”

https://cvc.cervantes.es/literatura/cuadernos_del_norte/pdf/23/23_10.pdf

Code
dich <- dictionary(
  list(
    hombres=
      list(
           Alvaro=c("Álvaro Mesía",
                    "Álvaro",
                    "Mesía",
                    "presidente del casino"),
           Saturnino=c("Saturnino Bermúdez",
                       "Saturnino",
                       "Bermúdez",
                       "Saturno",
                       "Saturnillo"),
           Fermin=c("Magistral",
                    "Provisor",
                    "Fermín",
                    "De Pas",
                    "Fermín de Pas",
                    "Magistral"),
           Victor=c("Víctor",
                    "Víctor Quintanar",
                    "Quintanar"),
           Otros=c(
                   "Agustinito",
                   "Amadeo",
                   "Anacleto",
                   "Anselmo",
                   "Antero",
                   "Antón Raíces",
                   "Antonio",
                   "Barcaza",
                   "Basilio",
                   "Bautista",
                   "Bedoya",
                   "Belisario",
                   "Benítez",
                   "Bismark",
                   "Campillo","\\b[C]hato\\b",
                   "don Carlos",
                   "Peláez",
                   "Cayetano","Cayetano Ripamilán","Ripamilán",
                   "Celedonio",
                   "Colás",
                   "marqués de Corujedo",
                   "Frígilis","Crespo",
                   "Custodio",
                   "Olías de Cuervo","señor Cuervo",
                   "Diego",
                   "Escosura",
                   "\\b[E]studiante\\b","Pepe","Trabuco",
                   "Foja",
                   "Fortunato",
                   "Francisco de Asís",
                   "Francisco de Pas",
                   "Francisco de Osuna",
                   "Francisco Páez", "señor Páez", "señor de Páez",
                   "Francisco Carraspique",
                   "Froilán",
                   "don Frutos","Frutos Redondo",
                   "Fulgosio",
                   "Germán",
                   "Glocester","Restituto",
                   "señor Infanzón", "el Infanzón",
                   "Iriarte",
                   "Joaquinito",
                   "Juanito",
                   "Leando",
                   "Maroto",
                   "marqués de Vegallana","\\s{1}[M]arqués\\b",
                   "Martínez",
                   "Matías",
                   "Matiella",
                   "monaguillo",
                   "señor Orgaz",
                   "\\b[P]alma\\b",
                   "Paco","Paquito",
                   "Palomo","Rodríguez",
                   "Parcerisa",
                   "Pedro",
                   "\\b[P]erales\\b",
                   "Pinón",
                   "Pompeyo","Pompeyo Guimarán","Guimarán",
                   "Robustiano",
                   "señor Roque",
                   "Rosendo",
                   "don Santos",
                   "Sousa",
                   "Trifón",
                   "\\b[V]inagre\\b",
                   "Vinculete")
           ),
    mujeres=
      list(
        Ana=c("Ana",
              "Anita",
              "Regenta"),
        Obdulia=c("Obdulia",
                  "Obdulia Fandiño",
                  "Fandiño",
                  "Obdulita"),
        Otras=c(
                "Agapita",
                "Águeda",
                "Angelina",
                "Anuncita",
                "doña Anuncia",
                "Camila",
                "Carolina","Señora de Infanzón", "la Infanzón",
                "Celestina",
                "Edelmira",
                "Emma",
                "Fabiolita",
                "Fulgencia",
                "Gertrudis",
                "la González",
                "Juana",
                "Lola",
                "doña Lucía",
                "marquesa","Rufina",
                "Olvido",
                "doña Paula",
                "Pepa",
                "Guimarán, Perpétua",
                "\\b[P]ilar\\b",
                "Petra",
                "doña Petronila",
                "Ramona",
                "\\bRita\\b",
                "\\bRosa\\b",
                "Rosita",
                "Rudesinda",
                "Servanda",
                "Társila",
                "\\b[T]eresa\\b",
                "Teresina",
                "Úrsula",
                "Visitación",
                "\\b[V]isita\\b",
                "viuda del marqués de Corujedo")
    )
  )
)




xp <- countKeywords(cp, 
                    dich, 
                    rel.freq = F, 
                    group.var = "capitulo",
                    quietly = TRUE)

# Agrega los resultados por los dos niveles
# de código del diccionario
xx <- aggregate(list(frequency=xp$frequency), 
                by=list(groups=xp$groups, 
                        level1=xp$level2), 
                sum, na.rm=T)

# Elimina los términos no encontrados
# en el corpus
xx <- xx[xx$frequency>0,]

# Ordena por capítulo
xx <- xx[order(xx$groups),]

plotSankey(xx, 
           from = "level1", 
           to="groups", 
           value = "frequency", 
           opacity = 0.05)

dddd

Code
# Reorganiza el corpus según
# sentencias o frases
cs <- corpus_reshape(cp, "sentences")

# Calcula la frecuencia en la
# que dos codigos del mismo 
# diccionario aparecen juntos
# en cada frase
d1 <- matchCodes(cs, 
                dic, 
                level = 1, 
                quietly=TRUE)

# Ordena los resultados de mayor a menor
d1 <- d1[order(d1$value, decreasing = T),]


plotChord(d1, 
          from = "term1", 
          to ="term2", 
          value= "value")

Ahora con los personajes

Code
# Reorganiza el corpus según
# sentencias o frases
cs <- corpus_reshape(cp, "sentences")

# Calcula la frecuencia en la
# que dos codigos del mismo 
# diccionario aparecen juntos
# en cada frase
d1 <- matchCodes(cs, 
                dich, 
                level = 2, 
                quietly=TRUE)

# Ordena los resultados de mayor a menor
d1 <- d1[order(d1$value, decreasing = T),]


plotChord(d1, 
          from = "term1", 
          to ="term2", 
          value= "value", elementId = "chord2")

aaa